package com.wjyf.reducing_bento.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wjyf.reducing_bento.common.ErrorCode;
import com.wjyf.reducing_bento.model.dto.LoginUserDto;
import com.wjyf.reducing_bento.model.dto.UserRegisterDto;
import com.wjyf.reducing_bento.model.entity.UserBean;
import com.wjyf.reducing_bento.exception.BusinessException;
import com.wjyf.reducing_bento.mapper.UserMapper;
import com.wjyf.reducing_bento.service.InviteRecordService;
import com.wjyf.reducing_bento.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wjyf.reducing_bento.utils.JwtUtils;
import com.wjyf.reducing_bento.utils.Md5Utils;
import com.wjyf.reducing_bento.model.vo.UserLoginVo;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import java.time.LocalDateTime;
import java.util.List;

import static com.wjyf.reducing_bento.common.ErrorCode.*;
import static com.wjyf.reducing_bento.constant.UserConstant.*;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author wjyf
 * @since 2023-03-14 08:36:33
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserBean> implements UserService {

    @Resource
    private InviteRecordService inviteRecordService;

    @Override
    public UserBean login(LoginUserDto loginUserDto, HttpServletRequest request) {
        if (loginUserDto == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        String uPhon = loginUserDto.getUPhon();
        String uPassword = loginUserDto.getUPassword();
        if (StringUtils.isAnyBlank(uPassword, uPhon)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        UserBean userBean = getOne(
                new LambdaQueryWrapper<UserBean>()
                        .eq(UserBean::getUPhon, uPhon)
                        .eq(UserBean::getUPassword, Md5Utils.encryption(uPassword))
        );
        if (userBean == null) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "账号或密码错误");
        }
        String token = JwtUtils.createJWT(userBean.getUId().toString());
        UserLoginVo userLoginVo = new UserLoginVo();
        BeanUtil.copyProperties(userBean, userLoginVo);
        userLoginVo.setToken(token);
        return userLoginVo;

    }

    @Override
    public UserBean getUser(HttpServletRequest request) {
        String token = request.getHeader("token");
        String userId = null;
        try {
            Claims claims = JwtUtils.parseJWT(token);
            userId = claims.getSubject();
        } catch (Exception e) {
            throw new BusinessException(PARAMS_ERROR, "非法token");
        }
        if (StringUtils.isBlank(userId)) {
            throw new BusinessException(PARAMS_ERROR, "非法token");
        }
        UserBean userBean = this.getById(Long.valueOf(userId));

        return userBean;
    }

    private void updateSessionUser(UserBean userBean, HttpServletRequest request) {
        request.getSession().setAttribute(USER_SESSION_KEY, userBean);
    }

    public boolean isAdmin(HttpServletRequest request) {
        UserBean user = getUser(request);
        String uPower = user.getUPower();
        boolean isAdmin = uPower.equalsIgnoreCase(ADMIN);
        if (!isAdmin) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        return isAdmin;
    }

    @Override
    public boolean recharge(Double money, Long userId) {
        if (money == null || money <= 0 || userId == null || userId <= 0) {
            throw new BusinessException(PARAMS_ERROR);
        }
        boolean result = false;
        synchronized (this) {
            UserBean userBean = this.getById(userId);
            if (userBean == null) {
                throw new BusinessException(PARAMS_ERROR);
            }
            userBean.setUBalanc(money + userBean.getUBalanc());
            result = this.updateById(userBean);
        }
        return result;
    }

    @Override
    public Page<UserBean> getUserPage(Long current, Long pageSize, String key) {
        if (current == null || pageSize == null || current <= 0 || pageSize <= 0) {
            throw new BusinessException(PARAMS_ERROR);
        }
        LambdaQueryWrapper<UserBean> wrapper = new LambdaQueryWrapper<>();
        if (wrapper != null && !StringUtils.isBlank(key)) {
            wrapper.like(UserBean::getUPhon, key).or().like(UserBean::getUName, key);
        }
        return this.page(new Page<UserBean>(current, pageSize), wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean register(UserRegisterDto userRegisterDto) {
        if (userRegisterDto == null) {
            throw new BusinessException(PARAMS_ERROR);
        }
        String uPassword = userRegisterDto.getUPassword();
        String uName = userRegisterDto.getUName();
        String uSex = userRegisterDto.getUSex();
        String uPhon = userRegisterDto.getUPhon();
        String inviteCode = userRegisterDto.getInviteCode();
        if (StringUtils.isAnyBlank(uPassword, uName, uSex, uPhon)) {
            throw new BusinessException(PARAMS_ERROR);
        }
        if (!uPhon.matches(PHONE_NUMBER)) {
            throw new BusinessException(PARAMS_ERROR, "请输入正确的手机号码");
        }
        List<UserBean> userBeans = this.list(new LambdaQueryWrapper<UserBean>().eq(UserBean::getUPhon, uPhon));
        if (!userBeans.isEmpty()) {
            throw new BusinessException(OPERATION_ERROR, "该手机号码以及被注册");
        }
        UserBean userBean = new UserBean();
        BeanUtil.copyProperties(userRegisterDto, userBean);
        userBean.setUBalanc(DEFAULT_BALANCE)
                .setUFlag(NORMAL_FLAG)
                .setUPower(USER)
                .setUPassword(Md5Utils.encryption(userBean.getUPassword()))
                .setUPhon(uPhon)
                .setInviteCode(IdUtil.simpleUUID())
                .setCreateTime(LocalDateTime.now());
        boolean save = save(userBean);
        if (StringUtils.isNotBlank(inviteCode)) {
            // 有邀请码
            inviteRecordService.bindInviter(inviteCode, userBean.getUId());
        }
        return save;
    }

    @Override
    public UserBean getUserInfo(HttpServletRequest request) {
        UserBean user = this.getUser(request);
        return this.getById(user);
    }
}
